home *** CD-ROM | disk | FTP | other *** search
- /*
- +---------------------------------------------------------------+
- | RealTime 2.5d Landscape Sculpting ! |
- +---------------------------------------------------------------+
-
- usage: run it, preferably selecting lowres from the requester,
- the sculpt with leftmouse, quit with rightmouse.
-
- sculpting is done as follows: two halfs of the screen (left-right)
- influence the height of the two sides of the landscape. You'll need
- to experiment a bit to get an idea what you can accomplish this way.
-
- for further fun: try and recompile with a different #define for
- `trans()' further down the source.
-
- The code is pretty OS friendly (using intuition double-buffering
- etc.), I hope it also works on gfx-cards (don't know about the
- chunky code though).
-
- The sculpting bit is only a demo for the underlying engine, which
- could display _any_ animated 3d landscape in realtime [it
- should be fast enough on anything from an A1200+fast upwards]
-
- */
-
- OPT OSVERSION=39, PREPROCESS
-
- CONST CWIDTH=256,CHEIGHT=128,CWSHIFT=8
- CONST SCHEIGHT=CHEIGHT+20
- CONST TEMPBUFS=CWIDTH*CHEIGHT/2,BUFS=CWIDTH*CHEIGHT,BUFM=$7FFF
- CONST SXOFF=50,SYOFF=80
- CONST XY3D=80
-
- MODULE '*c2p4', '*screenmodereq_db', 'tools/exceptions', 'tools/scrbuffer',
- 'intuition/screens', 'graphics/rastport', 'graphics/gfx',
- 'intuition/intuition', 'devices/inputevent'
-
- DEF sideh[XY3D]:ARRAY OF LONG, both[XY3D]:ARRAY OF LONG
-
- PROC main() HANDLE
- DEF dbs,scr=NIL:PTR TO screen,bm:PTR TO bitmap,win=NIL:PTR TO window,
- tbuf2,tbuf3,tbuf2b,tbuf3b,cbuf,dbuf,dbuf2,lsbuf,sigbit,sig,safe=TRUE,a,x=0,y=0,
- imsg:PTR TO intuimessage,temp,lastx=-1,lasty=-1,quit=FALSE
- IF (dbs:=openreqscreen(CWIDTH,SCHEIGHT,4,'2.5d'))=NIL THEN Raise()
- scr:=sb_GetScreen(dbs)
- IF (win:=OpenW(0,0,CWIDTH-1,SCHEIGHT-1,
- IDCMP_MOUSEBUTTONS OR IDCMP_MOUSEMOVE,
- WFLG_REPORTMOUSE OR WFLG_BORDERLESS OR WFLG_SIMPLE_REFRESH OR WFLG_BACKDROP OR WFLG_ACTIVATE OR WFLG_RMBTRAP,
- '',scr,15,NIL))=NIL THEN Raise("WIN")
- tbuf2:=NewM(TEMPBUFS+TEMPBUFS,2)
- tbuf3:=tbuf2+TEMPBUFS
- tbuf2b:=NewM(TEMPBUFS+TEMPBUFS,2)
- tbuf3b:=tbuf2b+TEMPBUFS
- NEW cbuf[BUFS]
- NEW dbuf[BUFS]
- NEW dbuf2[BUFS]
- NEW lsbuf[BUFS]
- FOR a:=0 TO BUFS-1
- dbuf[a]:=-1
- dbuf2[a]:=-1
- ENDFOR
- FOR a:=0 TO XY3D-1
- sideh[a]:=15
- both[a]:=15
- ENDFOR
- ->FOR a:=0 TO 15 DO SetColour(scr,15-a,a*16,(15-a)*16,240)
- FOR a:=0 TO 15 DO SetColour(scr,15-a,a*16,a*16,a*16)
- FOR a:=0 TO BUFS-1 DO cbuf[a]:=15
- CopyMem(cbuf,lsbuf,BUFS)
- SetRast(scr.rastport,0)
- IF (sigbit:=AllocSignal(-1))<>-1
- sig:=Shl(1,sigbit)
- REPEAT
- render(cbuf,lsbuf,0,XY3D,XY3D)
- IF safe=FALSE
- Wait(sig)
- safe:=TRUE
- ENDIF
- bm:=sb_NextBuffer(dbs)
- c2p4(tbuf3,tbuf2,cbuf,dbuf,bm.planes,FindTask(NIL),sig,gfxbase)
- temp:=dbuf; dbuf:=dbuf2; dbuf2:=temp
- temp:=tbuf2; tbuf2:=tbuf2b; tbuf2b:=temp
- temp:=tbuf3; tbuf3:=tbuf3b; tbuf3b:=temp
- WHILE imsg:=GetMsg(win.userport)
- x:=imsg.mousex; y:=imsg.mousey
- IF imsg.qualifier AND IEQUALIFIER_RBUTTON THEN quit:=TRUE
- IF (imsg.class=IDCMP_MOUSEBUTTONS) AND (imsg.code=SELECTUP)
- lastx:=-1; lasty:=-1
- ENDIF
- IF imsg.qualifier AND IEQUALIFIER_LEFTBUTTON
- IF lastx>=0
- WHILE lastx<>x
- IF lastx>x THEN lastx-- ELSE lastx++
- press(lastx,y,lsbuf)
- ENDWHILE
- ELSE
- press(lastx:=x,lasty:=y,lsbuf)
- ENDIF
- ENDIF
- ReplyMsg(imsg)
- ENDWHILE
- safe:=FALSE
- UNTIL quit
- IF safe=FALSE THEN Wait(sig)
- FreeSignal(sigbit)
- ENDIF
- EXCEPT DO
- IF win THEN CloseWindow(win)
- closereqscreen(dbs)
- SELECT exception
- CASE "SCR"; WriteF('no screen!\n')
- CASE "REQ"; WriteF('Error: Could not allocate ASL request\n')
- CASE "ASL"; WriteF('Error: Could not open ASL library\n')
- ENDSELECT
- report_exception()
- ENDPROC
-
- PROC press(mx,my,buf)
- DEF height,xc,lr
- mx:=Bounds(mx,0,CWIDTH-1)
- my:=Bounds(my,0,SCHEIGHT-1)
- height:=my*16/SCHEIGHT
- xc,lr:=Mod(mx,CWIDTH/2)
- xc:=xc*XY3D*2/CWIDTH
- IF lr THEN side_sculpt(XY3D-1-xc,buf,height) ELSE bot_sculpt(xc,buf,height)
- ENDPROC
-
- #define trans(a,b) a + b / 2
- ->#define trans(a,b) Eor(a,b)
- ->#define trans(a,b) Max(a,b)
- ->#define trans(a,b) Min(a,b)
-
- PROC bot_sculpt(off,buf,h)
- DEF p,a,sh:PTR TO LONG
- p:=off+buf
- both[off]:=h
- sh:=sideh
- FOR a:=0 TO XY3D-1
- p[]:=trans(sh[]++,h)
- p:=p+CWIDTH
- ENDFOR
- ENDPROC
-
- PROC side_sculpt(off,buf,h)
- DEF p,a,bh:PTR TO LONG
- p:=off*CWIDTH+buf
- sideh[off]:=h
- bh:=both
- FOR a:=0 TO XY3D-1 DO p[]++:=trans(bh[]++,h)
- ENDPROC
-
- PROC render(destbuf,lsbuf,offs,xs,ys)
- DEF a,t1,t2
- clearmem(destbuf,BUFS)
- t1:=ys-1*CWIDTH-1+offs
- t2:=xs-1+offs
- FOR a:=1 TO xs DO line(a,t1+a AND BUFM,a+SXOFF,a/2+SYOFF,destbuf,lsbuf)
- FOR a:=ys-1 TO 1 STEP -1 DO line(a,a-1*CWIDTH+t2 AND BUFM,xs*2+SXOFF-a,a/2+SYOFF,destbuf,lsbuf)
- ENDPROC
-
- PROC clearmem(mem,size)
- DEF e:REG,a:REG,b:REG,c:REG,d:REG
- e:=size/16-1
- a:=b:=c:=d:=$04040404
- MOVE.L mem,A0
- ADD.L size,A0
- clloop:
- MOVEM.L a/b/c/d,-(A0)
- DBRA e,clloop
- ENDPROC
-
- PROC line(num,start,sx,sy,destbuf,lsbuf)
- DEF a:REG,y,t:REG,c=0:REG,xoff:REG,yoff:REG
- xoff:=sx+destbuf
- yoff:=sy-25-num+1
- y:=sy*CWIDTH+xoff
- a:=num-1+yoff
- MOVE.L start,D2 -> D2=start
- MOVEA.L lsbuf,A3 -> A3=lsbuf
- MOVE.L y,A2 -> A2=y
- MOVE.L #CWIDTH,D1 -> D1=CWIDTH
- MOVE.L #BUFM,D0 -> D0=BUFM
- MOVE.L #CWIDTH+1,A1 -> A1=CWIDTH+1
- bloop: -> this loop eats most cpu-time.
- MOVE.B 0(A3,D2.L),c
- MOVE.L a,t
- ADD.L c,t
- LSL.L #CWSHIFT,t
- ADD.L xoff,t
- CMP.L A2,t
- BGE.S skip
- BRA.S loop
- begi:
- SUBA.L D1,A2
- MOVE.B c,(A2)
- loop:
- CMP.L A2,t
- BMI.S begi
- skip:
- SUB.L A1,D2
- AND.L D0,D2
- SUBQ.L #1,a
- CMP.L yoff,a
- BPL.S bloop
- ENDPROC
-